home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / metamail / contrib / ServiceMail / src / mesh / mailout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-18  |  9.0 KB  |  312 lines

  1. /*
  2.  * mailout.c -- functions to compose service response
  3.  *
  4.  * 18-Feb-93 weber@eitech.com added ENCODING field to override encoding
  5.  * 18-Feb-93 weber@eitech.com passes SPLITSIZE to splitmail
  6.  * 18-Feb-93 weber@eitech.com added several outgoing header lines
  7.  * 27-Jun-92 weber@eitech.com marked ServiceMail(tm) v1.0
  8.  * 19-Jun-92 weber@eitech.com
  9.  *
  10.  * Copyright (c)  1992 Enterprise Integration Technologies Corporation
  11.  *
  12.  * Permission to use, copy, modify, distribute, and sell this software and 
  13.  * its documentation for any purpose is hereby granted without fee, provided
  14.  * that (i) the above copyright notices and this permission notice appear in
  15.  * all copies of the software and related documentation, and (ii) the name of
  16.  * Enterprise Integration Technologies Corporation may not be used in any 
  17.  * advertising or publicity relating to the software without the specific, 
  18.  * prior written permission of Enterprise Integration Technologies Corporation.
  19.  * 
  20.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  21.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  22.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  23.  *
  24.  * IN NO EVENT SHALL ENTERPRISE INTEGRATION TECHNOLOGIES CORPORATION  BE
  25.  * LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
  26.  * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  27.  * PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
  28.  * THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  29.  * PERFORMANCE OF THIS SOFTWARE.
  30.  */
  31.  
  32. #include <tcl.h>
  33. #include <sys/time.h>
  34. #include <time.h>
  35. #include <stdio.h>
  36. #include <ctype.h>
  37. #include <sys/types.h>
  38. #include <unistd.h>
  39.  
  40. #include "mesh.h"
  41.  
  42. #define NO_ENCODING 1
  43. #define QP_ENCODING 2
  44. #define BASE64_ENCODING 3
  45. #define SURVEY_SIZE 10000
  46. #define BLKSIZE 512
  47. #define MAXMIMELINELEN 75
  48.  
  49. int mailout(clientData, interp, argc, argv)
  50.      ClientData clientData;
  51.      Tcl_Interp *interp;
  52.      int argc;
  53.      char **argv;
  54. {
  55.   FILE *serv, *popen();
  56.   time_t time(), t;
  57.   int splitsize = 100000, i;
  58.   int subargc;
  59.   char **subargv;
  60.   char *to;
  61.   char buf[1024], m[256];
  62.   
  63.   if (argc != 3) {
  64.     interp->result = "wrong # of args to mailout proc";
  65.     return TCL_ERROR;
  66.   }
  67.   
  68.   Tcl_SplitList(interp, argv[1], &subargc, &subargv);
  69.  
  70.   for (i=0; i<subargc-1; i++)
  71.     if (!strcasecmp(subargv[i], "splitsize"))
  72.       splitsize = atoi(subargv[i+1]);
  73.  
  74. #ifdef MAILER
  75.   sprintf(m, MAILER, splitsize);
  76.   serv = popen(m, "w");
  77.   if (serv == NULL) {
  78.     interp->result = "Cannot start mailer process";
  79.     return TCL_ERROR;
  80.   }
  81. #else
  82.   serv = stdout;
  83. #endif
  84.  
  85.   while (subargc > 1) {
  86.     if (!strcasecmp(subargv[0], "to"))
  87.     {
  88.         to=subargv[1]; 
  89.     fprintf(serv, "To: %s\n", subargv[1]);
  90.     }
  91.     else if (!strcasecmp(subargv[0], "inreplyto"))
  92.       fprintf(serv, "In-Reply-To: %s\n", subargv[1]);
  93.     else if (!strcasecmp(subargv[0], "subject"))
  94.       fprintf(serv, "Subject: %s\n", subargv[1]);
  95.     else if (!strcasecmp(subargv[0], "cc"))
  96.       fprintf(serv, "Cc: %s\n", subargv[1]);
  97.     else if (!strcasecmp(subargv[0], "date"))
  98.       fprintf(serv, "Date: %s\n", subargv[1]);
  99.     else if (!strcasecmp(subargv[0], "messageid"))
  100.       fprintf(serv, "Message-Id: %s\n", subargv[1]);
  101.     else if (!strcasecmp(subargv[0], "from"))
  102.       fprintf(serv, "From: %s\n", subargv[1]);
  103.     else if (!strcasecmp(subargv[0], "splitsize"))
  104.       fprintf(serv, "X-Splitsize: %s\n", subargv[1]);
  105.     subargv += 2;
  106.     subargc -= 2;
  107.   }
  108.   free((char *) *subargv);
  109.   fprintf(serv, "MIME-Version: 1.0\n");
  110. #ifdef OUTBOX
  111.   fprintf(serv, "Bcc: %s\n", OUTBOX);
  112. #endif
  113.  
  114.   PrintMiffBodyRep(serv, argv[2]);
  115.     
  116. #ifdef MAILER
  117.   if (pclose(serv)) {
  118.     interp->result = "Mailer terminated with an error.";
  119. #ifdef FACILITY
  120.     if(logging)
  121.     {
  122.     openlog("mesh",(LOG_PID | LOG_CONS),loglevel);
  123.     syslog(loglevel | LOG_ALERT,"Mailer terminated with an error: Mail to:%s",to);
  124.      }    
  125. #endif
  126.     return TCL_ERROR;
  127.   }
  128. #endif
  129. #ifdef FACILITY
  130.     if(logging)
  131.      {
  132.        openlog("mesh",(LOG_PID | LOG_CONS),loglevel);
  133.        syslog(loglevel | LOG_INFO,"Successfully mailed to %s.",to);
  134.      }     
  135. #endif
  136.   return TCL_OK;
  137. }
  138.  
  139. PrintMiffBodyRep(serv, tclvar)
  140.      char *tclvar;
  141.      FILE *serv;
  142. {
  143.   Tcl_Interp *interp;
  144.   
  145.   PrintMiffSubBodyRep(serv, tclvar, interp = Tcl_CreateInterp());
  146.   Tcl_DeleteInterp(interp);
  147. }
  148.  
  149. PrintMiffSubBodyRep(serv, s, interp)
  150.      FILE *serv;
  151.      char *s;
  152.      Tcl_Interp *interp;
  153. {
  154.   int i;
  155.   char **argv, **argv2;
  156.   int argc, argc2;
  157.   char *type="text", *subtype="plain", *file=NULL, *description=NULL;
  158.   char *id=NULL, *string="Your service request was processed.";
  159.   char *params=NULL, *parts=NULL, encoding=0;
  160.   char boundary[80];
  161.   FILE *stream, *fopen();
  162.   
  163.   Tcl_SplitList(interp, s, &argc, &argv);
  164.   for (i=0; i<argc; i+=2) {
  165.     if (!strcasecmp(argv[i], "type")) type = argv[i+1];
  166.     else if (!strcasecmp(argv[i], "subtype")) subtype = argv[i+1];
  167.     else if (!strcasecmp(argv[i], "description")) description = argv[i+1];
  168.     else if (!strcasecmp(argv[i], "id")) id = argv[i+1];
  169.     else if (!strcasecmp(argv[i], "file")) file = argv[i+1];
  170.     else if (!strcasecmp(argv[i], "string")) string = argv[i+1];
  171.     else if (!strcasecmp(argv[i], "parts")) parts = argv[i+1];
  172.     else if (!strcasecmp(argv[i], "params")) params = argv[i+1];
  173.     else if (!strcasecmp(argv[i], "encoding")) {
  174.       if (!strcasecmp(argv[i+1], "base64")) encoding = BASE64_ENCODING;
  175.       else if (!strcasecmp(argv[i+1], "quoted-printable")) encoding = QP_ENCODING;
  176.       else encoding = NO_ENCODING;
  177.     }
  178.   }
  179.   if (id == NULL) id = file; /* id defaults to filename */
  180.  
  181.   if (id) fprintf(serv, "Content-Id: %s\n", id);
  182.   if (description) fprintf(serv, "Content-Description: %s\n", description);
  183.   fprintf(serv, "Content-Type: %s/%s", type, subtype);
  184.   if (params && *params) {
  185.     Tcl_SplitList(interp, params, &argc2, &argv2);
  186.     for (i=0; i<argc2; i+=2) {
  187.       fprintf(serv, "; %s=\"%s\"", argv2[i], argv2[i+1]);
  188.     }
  189.     free((char *) argv2);
  190.   }
  191.   else if (!strcasecmp(type, "text")) fputs("; charset=us-ascii", serv);
  192.  
  193.   if (!strcasecmp(type, "multipart") && parts) {
  194.     new_boundary(boundary);
  195.     fprintf(serv, "; boundary=\"%s\"\n\n", boundary);
  196.     Tcl_SplitList(interp, parts, &argc2, &argv2);
  197.     for (i=0; i<argc2; i++) {
  198.       fprintf(serv, "\n--%s\n", boundary);
  199.       PrintMiffSubBodyRep(serv, argv2[i], interp);
  200.     }
  201.     free((char *) argv2);
  202.     fprintf(serv, "\n--%s--\n", boundary);
  203.   }
  204.   else {
  205.     fputc('\n', serv);
  206.     if (file) {
  207.       if (stream = fopen(file, "r")) {
  208.     switch (encoding ? encoding : needs_encoding(stream, type, subtype)) {
  209.     case QP_ENCODING:
  210.       fputs("Content-Transfer-Encoding: quoted-printable\n\n", serv);
  211.       toqp(stream, serv);
  212.       break;
  213.     case BASE64_ENCODING:
  214.       fputs("Content-Transfer-Encoding: base64\n\n", serv);
  215.       to64(stream, serv);
  216.     default:
  217.       fputc('\n', serv);
  218.       to7bit(stream, serv);
  219.       break;
  220.     }
  221.       }
  222.       else {
  223.     fputs(s, stderr);
  224.     ErrorExit("some file does not exist!");
  225.       }
  226.     }
  227.     else {
  228.       fputc('\n', serv);
  229.       fputs(string, serv);
  230.       fputc('\n', serv);
  231.     }
  232.   }
  233.   free((char *) argv);
  234. }
  235.  
  236. /*
  237.   needs_encoding(FILE *f) scans the first SURVEY_SIZE bytes from f and
  238.   
  239.   if more than 10% of the bytes are unprintable, return BASE64_ENCODING
  240.   else if any lines are longer than 75 characters or any bytes are
  241.   unprintable, return QP_ENCODING
  242.   else return NO_ENCODING
  243.   */
  244.  
  245. int needs_encoding(fp, type, subtype)
  246.      FILE *fp;
  247.      char *type, *subtype;
  248. {
  249.    int pos = 0;            /* position in file */
  250.    int printable = 0;        /* num of printable chars seen so far */
  251.    char line[MAXMIMELINELEN+2];    /* the next line from file */
  252.    int len;            /* length of a line */
  253.    int c;            /* next char read from file */
  254.    
  255.    while ((pos <= SURVEY_SIZE) && ((c = getc(fp)) != EOF)) {
  256.       if (isascii(c) && (isprint(c) || isspace(c))) printable++;
  257.       pos++;
  258.    }
  259.    rewind(fp);
  260.  
  261.    /* Are more than 1/10 of chars unprintable? Then return BASE64_ENCODING */
  262.    if (pos/(pos-printable+1) < 10) return BASE64_ENCODING;
  263. #ifdef CHECKFORNOENCODING
  264.    /* If ANY bytes are unprintable return QP_ENCODING */
  265.    if (printable < pos) return QP_ENCODING;
  266.    
  267.    /*  else if any lines are longer than MAXMIMELINELEN characters,
  268.     *  then return QP_ENCODING */
  269.  
  270.    /* read file a line at a time */
  271.    for (pos = 0;fgets(line,MAXMIMELINELEN+2,fp) != NULL;) {
  272.       if (pos > SURVEY_SIZE) {
  273.     rewind(fp);
  274.     return NO_ENCODING;
  275.       }
  276.       len = strlen(line) -1;
  277.       if (len > MAXMIMELINELEN) {
  278.     rewind(fp);
  279.     return QP_ENCODING;
  280.       }
  281.       pos += len+1;        /* keep track of position in file */
  282.    }
  283.    rewind(fp);
  284.    return NO_ENCODING;
  285. #else
  286.   return QP_ENCODING; /* why not? NO_ENCODING is a special case of QP */
  287. #endif
  288. }
  289.  
  290. to7bit(inf, outf)
  291.      FILE *inf, *outf;
  292. {
  293.   char buf[BUFSIZ];
  294.   int items;
  295.  
  296.   while(items = fread(buf, sizeof(char), BUFSIZ, inf))
  297.     fwrite(buf, sizeof(char), items, outf);
  298. }
  299.  
  300. #define MAXHOSTNAMELEN 256
  301.  
  302. new_boundary(buf)
  303.      char *buf;
  304. {
  305.   static int ctr=0;
  306.   char hname[MAXHOSTNAMELEN];
  307.  
  308.   gethostname(hname, MAXHOSTNAMELEN);
  309.   sprintf(buf, "boundary.%s.%d.%d.%d", hname, getuid(), getpid(),
  310.       ctr++);
  311. }
  312.